﻿using System;
using System.Net;
using System.Windows;
using System.Net.Sockets;
using SilverlightClientLibrary.Messages;

namespace SilverlightClientLibrary.Clients
{
    public class SilverlightUdpClient
    {
        private UdpAnySourceMulticastClient _client;
        private byte[] _buffer = new byte[16];

        public IPEndPoint IP;

        public event Action<bool> EndJoinGroupEvent;
        public event Action EndSendMessageEvent;
        public event Action<IPEndPoint> MessageReceived;

        //public event Action<PointMessage> PointMessageReceived;

        public SilverlightUdpClient(Application App, Action<bool> endJoinGroup, Action endSendMessage, Action<IPEndPoint> messageReceived, Action<PointMessage> pointMessageReceived)
        {
            _client = new UdpAnySourceMulticastClient(IPAddress.Parse("230.87.54.122"), 3000);
            BeginJoinGroup();

            _buffer[0] = 1;

            EndJoinGroupEvent += endJoinGroup;
            EndSendMessageEvent += endSendMessage;
            //PointMessageReceived += pointMessageReceived;
            MessageReceived += messageReceived;

            App.Exit += new EventHandler(Current_Exit);
        }

        void Current_Exit(object sender, EventArgs e)
        {
            this._client.Dispose();
        }

        public void BeginJoinGroup()
        {
            try
            {
                _client.BeginJoinGroup(result =>
                    {

                        _client.EndJoinGroup(result);
                        _client.ReceiveBufferSize = _buffer.Length;
                        _client.SendBufferSize = _buffer.Length;

                        //DetermineIP();
                        //while (IP == null) { }

                        //BeginSendMessage(new BlankMessage());
                        BeginReceiveMessage();

                        EndJoinGroupEvent(true);
                    },
                        null);
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc.ToString());
                if (EndJoinGroupEvent != null)
                    EndJoinGroupEvent(false);
            }
        }

        //private void DetermineIP()
        //{
        //    IPEndPoint ip = null;
        //    while (_buffer[0] != 0)
        //    {
        //        Message blankMessage = new BlankMessage();
        //        byte[] bytes = blankMessage.Encode();
        //        _client.BeginSendToGroup(bytes, 0, bytes.Length,
        //            r =>
        //            {
        //                _client.EndSendToGroup(r);
        //                _client.BeginReceiveFromGroup(_buffer, 0, 1,
        //                    r2 =>
        //                    {
        //                        _client.EndReceiveFromGroup(r2, out ip);
        //                    },
        //                        null);
        //            },
        //                null);
        //    }
        //    IP = ip;
        //}

        public void BeginSendMessage(Message m)
        {
            byte[] buffer = m.Encode();
            _client.BeginSendToGroup(buffer, 0, buffer.Length, result =>
                {
                    _client.EndSendToGroup(result);
                    if (EndSendMessageEvent != null)
                        this.EndSendMessageEvent();
                },
                    null);
        }

        public void BeginReceiveMessage()
        {
            _client.BeginReceiveFromGroup(_buffer, 0, _buffer.Length, result =>
                {
                    IPEndPoint ip;
                    _client.EndReceiveFromGroup(result, out ip);
                    MessageReceived(ip);
                    BeginReceiveMessage();
                    //if (ip != this.IP)
                    //    DecodeMessage(_buffer);
                    //else if (ip == this.IP)
                    //    BeginReceiveMessage();
                },
                null);
        }

        private void DecodeMessage(byte[] buffer)
        {
            byte messageType = buffer[0];

            //switch (messageType)
            //{
            //    case BlankMessage.MessageType:
            //        break;
            //    case PointMessage.MessageType:
            //        PointMessage pm = new PointMessage(new Point(), IP);
            //        pm.Decode(_buffer);
            //        PointMessageReceived(pm);
            //        break;
            //}
        }
    }
}
